<template>
  <div class="icon-box">
    <el-input
      ref="inputRef"
      v-model="valueIcon"
      v-bind="$attrs"
      :placeholder="placeholder"
      :clearable="clearable"
      @clear="clearIcon"
      @click="openDialog"
    >
      <template #append>
        <svg-icon :name="valueIcon" />
      </template>
    </el-input>
    <el-dialog v-model="dialogVisible" :title="placeholder" width="66%">
      <el-input v-model="inputValue" placeholder="搜索图标" size="large" :prefix-icon="Search" />
      <el-tabs v-model="tsbsName" tab-position="left" class="icon-tabs">
        <el-tab-pane label="本地图标" name="localSvg">
          <div class="icon-list" v-if="Object.keys(localSvgIconMap).length">
            <div v-for="item in Object.keys(localSvgIconMap)" :key="item" class="icon-item" @click="selectIcon(item)">
              <component :is="localSvgIconMap[item]" width="2.5rem" height="2.5rem" />
            </div>
          </div>
          <el-empty v-else description="未搜索到您要找的图标~" />
        </el-tab-pane>
        <el-tab-pane v-for="icon in iconifyIcons" :key="icon.name" :label="icon.name" :name="icon.name">
          <div class="icon-list" v-if="Object.keys(icon.icons).length">
            <div v-for="item in icon.icons" :key="item" class="icon-item" @click="selectIcon(item)">
              <iconify-icon :icon="`${icon.prefix}:${item}`" style="font-size: 2.5rem" />
            </div>
          </div>
          <el-empty v-else description="未搜索到您要找的图标~" />
        </el-tab-pane>
      </el-tabs>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import type { Component } from "vue";
import type { IconifyDataType, SelectIconProps } from "../type.d";
import { ref, computed, defineAsyncComponent, watch } from "vue";
import { Icon as IconifyIcon } from "@iconify/vue";
import SvgIcon from "@/components/SvgIcon";
import iconData from "../iconData";

import Search from "~icons/ep/search";

const props = withDefaults(defineProps<SelectIconProps>(), {
  modelValue: "",
  title: "请选择图标",
  clearable: true,
  placeholder: "请选择图标"
});

// 重新接收一下，防止打包后 clearable 报错
const valueIcon = ref(props.modelValue);

// open Dialog
const dialogVisible = ref(false);
const openDialog = () => (dialogVisible.value = true);

// 选择图标(触发更新父组件数据)
const emit = defineEmits<{
  "update:modelValue": [value: string];
}>();

const inputRef = ref();
// 监听搜索框值
const inputValue = ref("");
// tabs 默认选中
const tsbsName = ref("localSvg");

// 本地svg图标
const localSvgModules = import.meta.glob("@/assets/svg/*.svg");
const localSvgIconMap = computed((): Record<string, Component> => {
  const svgIconMap: Record<string, Component> = {};
  Object.keys(localSvgModules).forEach(path => {
    const iconName = path.replace("/src/assets/svg/", "").replace(".svg", "");
    if (inputValue.value && !iconName.includes(inputValue.value)) return;
    svgIconMap[iconName] = defineAsyncComponent(localSvgModules[path] as () => Promise<{ default: Component }>);
  });
  return svgIconMap;
});

// iconify 图标
const iconifyIcons = computed((): IconifyDataType[] => {
  return iconData.map(item => {
    return {
      ...item,
      icons: item.icons.reduce((acc, iconName) => {
        if (inputValue.value && !iconName.includes(inputValue.value)) return acc;
        acc[iconName] = iconName;
        return acc;
      }, {} as string[])
    };
  });
});

/**
 * 选择图标
 *
 * @param iconName 图标名称
 */
const selectIcon = (iconName: string) => {
  let iconPrefix = "";
  if (tsbsName.value === "localSvg") {
    iconPrefix = "local&";
  } else {
    const icon = iconData.find(item => item.name === tsbsName.value);
    if (icon) {
      iconPrefix = `iconify&${icon.prefix}:`;
    }
  }

  const fullIconName = iconPrefix + iconName;
  valueIcon.value = fullIconName;
  dialogVisible.value = false;
  emit("update:modelValue", fullIconName);
};

/**
 * 清空图标
 */
const clearIcon = () => {
  valueIcon.value = "";
  emit("update:modelValue", "");
};

watch(
  () => dialogVisible.value,
  (newVal: boolean) => {
    if (newVal) {
      inputValue.value = "";
    }
  }
);
</script>

<style scoped lang="scss">
.icon-tabs {
  .el-tab-pane {
    height: calc(60vh - 85px);
    overflow-y: scroll;
  }
}
.icon-box {
  width: 100%;
  .el-button {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: var(--el-text-color-regular);
  }
  :deep(.el-dialog__body) {
    padding: 25px 20px 20px;
    .el-input {
      margin-bottom: 10px;
    }
    .icon-list {
      display: grid;
      grid-template-columns: repeat(auto-fill, 115px);
      justify-content: space-evenly;
      max-height: 70vh;
      .icon-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        width: 42px;
        padding: 20px 30px;
        cursor: pointer;
        transition: all 0.2s;
        &:hover {
          transform: scale(1.3);
        }
        span {
          margin-top: 5px;
          line-height: 20px;
          text-align: center;
        }
      }
    }
  }
}
</style>
